package ch.cryptobox.encryption;

import java.util.ArrayList;
import java.util.Random;

public class ShamirSecretSharing {

	private static ShamirSecretSharing instance=null;
	
	private final static Random random=new Random();
	private int pices;
	private int[] keys;

	public static void main(String[] args) {
		String data="aasfditsdv skgdfgsg";
		ShamirSecretSharing sss=ShamirSecretSharing.getInstance(7);
		
		ArrayList<byte[]> ecr=sss.encrypt(data.getBytes());
		
		byte[] decr=sss.decrypt(ecr);
		
		System.out.println(new String(decr));
		System.out.println(new String(decr).equals(data));
	}
	
	public static ShamirSecretSharing getInstance(int n)
	{
		if(instance==null)
			instance=new ShamirSecretSharing(n);
		
		return instance;
	}

	public ArrayList<byte[]> encrypt(final byte[] data)
	{
		ArrayList<String> res=new ArrayList<String>(pices);

		for(int p=0;p<pices;++p)
			res.add("");

		for(int b=0;b<data.length;++b)
		{
			
			for(int xi=0;xi<pices;++xi){
				int v=data[b];
				int x0=xi+2;
				int x=x0;

				for(int p=0;p<pices-1;++p)
				{
					v+=x*keys[p];
					x*=x0;
				}
				
				String tmp=res.get(xi)+(xi+2)+";"+v+";";
				res.set(xi, tmp);
			}
		}
		
		ArrayList<byte[]> result=new ArrayList<byte[]>(pices);
		for(int p=0;p<pices;++p)
			result.add(res.get(p).getBytes());
		
		return result;
	}
	
	public byte[] decrypt(ArrayList<byte[]> data)
	{
		ArrayList<String> res=new ArrayList<String>(pices);
		for(int p=0;p<pices;++p)
			res.add(new String(data.get(p)));
		
		int lenght=res.get(0).split(";").length/2;
		
		
		ArrayList<int[]> serie=new ArrayList<int[]>();
		for(int i=0;i<lenght;++i)
			serie.add(new int[data.size()]);
		
		for(int i=0;i<res.size();++i)
		{
			String tmp=res.get(i);
			String[] split=tmp.split(";");
			
			for(int j=0;j<lenght;++j)
			{
				int index=Integer.parseInt(split[2*j])-2;
				serie.get(j)[index]=Integer.parseInt(split[j*2+1]);
				//System.out.println(split[j*2+1]);
			}
				
		}
		
		byte[] result=new byte[lenght];
		
		for (int b=0;b<serie.size();++b) {
			int[] s=serie.get(b);
			int val=0;
			
			for(int j=0;j<s.length;++j)
			{
				double lj=1;
				int yj=s[j];
				int xj=j+2;
				for(int m=0;m<s.length;++m)
				{
					if(m==j) continue;	
					
					double xm=m+2.0;
					
					lj*=(0-xm)/(xj-xm);
				}
				
				val+=lj*yj;
			}
			
			result[b]=(byte) val;
		}
		
		
		return result;
	}

	public void regenerateKey()
	{
		for(int i=0;i<pices-1;++i)
			keys[i]=random.nextInt(200);
	}

	private ShamirSecretSharing(int pices)
	{
		this.pices=pices;
		keys=new int[pices-1];
		regenerateKey();
	}
}
